package com.diandian.backend.dingding.data.service;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson2.JSON;
import com.diandian.backend.dingding.data.clients.MiddleClient;
import com.diandian.backend.dingding.data.clients.dto.OapiV2UserListResponse;
import com.diandian.backend.dingding.data.dto.*;
import com.diandian.backend.dingding.data.resp.DingdingDeptTreeListResp;
import com.diandian.backend.dingding.data.resp.DingdingStaffListResp;
import com.diandian.base.boot.starter.exception.DefaultException;
import com.diandian.base.boot.starter.response.BaseResult;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

@Service
public class DingdingStaffSyncService {

    private static final Logger logger = LoggerFactory.getLogger(DingdingStaffSyncService.class);

    @Autowired
    private DingdingDeptTreeService dingdingDeptTreeService;

    @Autowired
    private DingdingDeptTreeStaffService dingdingDeptTreeStaffService;

    @Autowired
    private MiddleClient middleClient;

    @Autowired
    private DingdingStaffService dingdingStaffService;

    @Value("${middle.appKey}")
    private String middleAppKey;

    @Value("${middle.appSecret}")
    private String middleAppSecret;

    private static List<String> USER_ID_CACHE = new ArrayList<>();

    /**
     * 拉取员工数据
     * @param appKey
     * @param appSecret
     * @param belong
     */
    @Transactional(rollbackFor = Exception.class)
    public void pullStaff(String appKey, String appSecret, String belong, Integer startIndex, Integer endIndex) {

        if(appKey == null || "".equals(appKey) || appSecret == null || "".equals(appSecret)){
            throw new DefaultException("密钥缺失");
        }
        if(belong == null || "".equals(belong)){
            throw new DefaultException("归属标识缺失");
        }

        // 获取部门数据
        DingdingDeptTreeListParamDTO deptListQueryDTO = new DingdingDeptTreeListParamDTO();
        deptListQueryDTO.setBelongEql(belong);
        List<DingdingDeptTreeListResp> deptList = dingdingDeptTreeService.getList(deptListQueryDTO);
        if(deptList == null || deptList.size() == 0){
            logger.info("拉取员工数据时未获取到部门数据，停止后续处理");
            throw new DefaultException("拉取员工数据时未获取到部门数据，停止后续处理");
        }

        if(startIndex != null && endIndex !=null && startIndex > 0 && startIndex <= endIndex && endIndex <= deptList.size()){
            logger.info("执行第{}个至第{}个门店员工数据拉取...", startIndex, endIndex);
            deptList = deptList.subList(startIndex -1 , endIndex);
        }

        logger.info("要拉取员工部门数量：{}", deptList.size());

        // 获取已存在员工数据
        List<String> existsUserIdList = queryExistsUserIdList(belong);

        USER_ID_CACHE = new ArrayList<>();

        for (int i = 0; i < deptList.size(); i++) {

            logger.info("开始拉取第{}个门店的员工数据...", i + 1);

            String deptCode = deptList.get(i).getDeptCode();
            if(deptCode == null || "".equals(deptCode)){
                logger.info("第{}个门店部门编号为空，跳过员工数据拉取...", i + 1);
                continue;
            }
            logger.info("开始拉取第{}个门店部门({})员工数据...", i + 1, deptCode);

            JSONObject jsonObject = new JSONObject();
            jsonObject.put("dingDeptId", deptCode);
            BaseResult baseResult = middleClient.getAllDeptUserDetail(middleAppKey, middleAppSecret, "dingding.exchange.dept.get.all.user.detail", jsonObject);
            if(baseResult == null || baseResult.getCode() != 0 || baseResult.getData() == null){
                logger.info("拉取第{}个门店部门({})员工数据异常。", i + 1, deptCode);
                throw new DefaultException("拉取门店部门({})员工数据异常");
            }

            BaseResult innerBaseResult = JSON.parseObject(JSON.toJSONString(baseResult.getData()), BaseResult.class);
            if(innerBaseResult == null || innerBaseResult.getCode() != 0 || innerBaseResult.getData() == null){
                logger.info("拉取第{}个门店部门({})员工数据异常。", i + 1, deptCode);
                throw new DefaultException("拉取门店部门({})员工数据异常");
            }

            List<OapiV2UserListResponse.ListUserResponse> staffList = JSONArray.parseArray(JSON.toJSONString(innerBaseResult.getData()), OapiV2UserListResponse.ListUserResponse.class);
            if(staffList == null || staffList.size() == 0){
                logger.info("拉取第{}个门店部门({})员工数据为空，跳过。", i + 1, deptCode);
                continue;
            }
            logger.info("获取到员工数量:{}", staffList.size());

            // 区分新增还是更新
            List<OapiV2UserListResponse.ListUserResponse> staffAddList = new ArrayList<>();
            List<OapiV2UserListResponse.ListUserResponse> staffUpdateList = new ArrayList<>();
            for (int j = 0; j < staffList.size(); j++) {
                String userId = staffList.get(j).getUserid();
                if(existsUserIdList.contains(userId)){
                    staffUpdateList.add(staffList.get(j));
                }else {
                    staffAddList.add(staffList.get(j));
                }
            }
            logger.info("待新增数量：{}，待更新数量：{}", staffAddList.size(), staffUpdateList.size());

            addData(staffAddList, belong);
            updateDate(staffUpdateList, belong);
        }

        USER_ID_CACHE = new ArrayList<>();

        logger.info("执行门店员工拉取完成。");
    }

    private List<String> queryExistsUserIdList(String belong){

        DingdingStaffListParamDTO staffListParamDTO = new DingdingStaffListParamDTO();
        staffListParamDTO.setBelongEql(belong);
        List<DingdingStaffListResp> list = dingdingStaffService.getList(staffListParamDTO);
        if(list == null || list.size() == 0){
            return new ArrayList<>();
        }

        return list.stream().map(DingdingStaffListResp::getUserId).collect(Collectors.toList());
    }

    private void addData(List<OapiV2UserListResponse.ListUserResponse> staffList, String belong){

        if(staffList == null || staffList.size() == 0){
            return;
        }

        List<DingdingStaffAddParamDTO> saveList = new ArrayList<>();
        List<DingdingDeptTreeStaffAddParamDTO> saveRelationList = new ArrayList<>();

        for (int j = 0; j < staffList.size(); j++) {
            OapiV2UserListResponse.ListUserResponse item = staffList.get(j);

            String userId = item.getUserid();
            if(userId != null && !"".equals(userId) && USER_ID_CACHE.contains(userId)){
                continue;
            }
            USER_ID_CACHE.add(userId);

            DingdingStaffAddParamDTO saveItem = new DingdingStaffAddParamDTO();
            saveItem.setBelong(belong);
            saveItem.setUserId(item.getUserid());
            saveItem.setUnionId(item.getUnionid());
            saveItem.setName(item.getName());
            saveItem.setAvatar(item.getAvatar());
            saveItem.setStateCode(item.getStateCode());
            saveItem.setMobile(item.getMobile());
            saveItem.setTelephone(item.getTelephone());
            saveItem.setJobNumber(item.getJobNumber());
            saveItem.setTitle(item.getTitle());
            saveItem.setEmail(item.getEmail());
            saveItem.setOrgEmail(item.getOrgEmail());
            saveItem.setWorkPlace(item.getWorkPlace());
            saveItem.setRemark(item.getRemark());
            if(item.getHiredDate() != null){
                saveItem.setHiredDate(new Date(item.getHiredDate()));
            }
            if(item.getActive() != null){
                saveItem.setActive(item.getActive() ? 1 : 0);
            }
            if(item.getAdmin() != null){
                saveItem.setAdmin(item.getAdmin() ? 1 : 0);
            }
            if(item.getBoss() != null){
                saveItem.setBoss(item.getBoss() ? 1 : 0);
            }
            if(item.getLeader() != null){
                saveItem.setLeader(item.getLeader() ? 1 : 0);
            }
            if(item.getExclusiveAccount() != null){
                saveItem.setExclusiveAccount(item.getExclusiveAccount() ? 1 : 0);
            }
            saveList.add(saveItem);

            if(userId != null && !"".equals(userId) && item.getDeptIdList() != null && item.getDeptIdList().size() > 0){
                List<Long> deptIdList = item.getDeptIdList();
                for (Long deptId : deptIdList) {
                    DingdingDeptTreeStaffAddParamDTO relation = new DingdingDeptTreeStaffAddParamDTO();
                    relation.setBelong(belong);
                    relation.setUserId(userId);
                    relation.setDeptCode(String.valueOf(deptId));
                    saveRelationList.add(relation);
                }
            }
        }

        // 保存员工信息数据
        dingdingStaffService.batchAdd(saveList);

        // 保存部门-员工关联数据
        dingdingDeptTreeStaffService.batchAdd(saveRelationList);
    }

    private void updateDate(List<OapiV2UserListResponse.ListUserResponse> staffList, String belong){

        if(staffList == null || staffList.size() == 0){
            return;
        }

        List<DingdingStaffUpdateByIdParamDTO> updateList = new ArrayList<>();
        List<DingdingDeptTreeStaffAddParamDTO> saveRelationList = new ArrayList<>();
        List<String> userIdList = new ArrayList<>();

        for (int j = 0; j < staffList.size(); j++) {
            OapiV2UserListResponse.ListUserResponse item = staffList.get(j);

            String userId = item.getUserid();
            if(userId == null || "".equals(userId) || belong == null || "".equals(belong)){
                continue;
            }
            userIdList.add(userId);

            DingdingStaffUpdateByIdParamDTO updateItem = new DingdingStaffUpdateByIdParamDTO();
            updateItem.setBelong(belong);
            updateItem.setUserId(item.getUserid());
            updateItem.setUnionId(item.getUnionid());
            updateItem.setName(item.getName());
            updateItem.setAvatar(item.getAvatar());
            updateItem.setStateCode(item.getStateCode());
            updateItem.setMobile(item.getMobile());
            updateItem.setTelephone(item.getTelephone());
            updateItem.setJobNumber(item.getJobNumber());
            updateItem.setTitle(item.getTitle());
            updateItem.setEmail(item.getEmail());
            updateItem.setOrgEmail(item.getOrgEmail());
            updateItem.setWorkPlace(item.getWorkPlace());
            updateItem.setRemark(item.getRemark());
            if(item.getHiredDate() != null){
                updateItem.setHiredDate(new Date(item.getHiredDate()));
            }
            if(item.getActive() != null){
                updateItem.setActive(item.getActive() ? 1 : 0);
            }
            if(item.getAdmin() != null){
                updateItem.setAdmin(item.getAdmin() ? 1 : 0);
            }
            if(item.getBoss() != null){
                updateItem.setBoss(item.getBoss() ? 1 : 0);
            }
            if(item.getLeader() != null){
                updateItem.setLeader(item.getLeader() ? 1 : 0);
            }
            if(item.getExclusiveAccount() != null){
                updateItem.setExclusiveAccount(item.getExclusiveAccount() ? 1 : 0);
            }
            updateList.add(updateItem);

            if(userId != null && !"".equals(userId) && item.getDeptIdList() != null && item.getDeptIdList().size() > 0){
                List<Long> deptIdList = item.getDeptIdList();
                for (Long deptId : deptIdList) {
                    DingdingDeptTreeStaffAddParamDTO relation = new DingdingDeptTreeStaffAddParamDTO();
                    relation.setBelong(belong);
                    relation.setUserId(userId);
                    relation.setDeptCode(String.valueOf(deptId));
                    saveRelationList.add(relation);
                }
            }
        }

        // 更新基础数据
        dingdingStaffService.batchUpdateByUserId(updateList);

        // 更新关联关系，先删再新增
        dingdingDeptTreeStaffService.deleteByBelongAndUserIdIn(belong, userIdList);
        dingdingDeptTreeStaffService.batchAdd(saveRelationList);
    }

}
